using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using Ltf.Remoting.TeamFoundation;
using System.IO;

namespace Ltf.Remoting.Server
{
	public class TcpServer
	{
		private ServerFunctions serverFunctions = new ServerFunctions();
		private string lastTmpFileName = string.Empty;

		private delegate void listenerStart();

		public void Start()
		{
			listenerStart ls = new listenerStart(StartListener);

			ls.BeginInvoke(null,null);

		}

		private void StartListener()
		{
			TcpListener server = null;
			try
			{
				// Set the TcpListener on port 13000.
				Int32 port = 5005;
				IPAddress localAddr = IPAddress.Parse("127.0.0.1");

				// TcpListener server = new TcpListener(port);
				server = new TcpListener(localAddr, port);

				// Start listening for client requests.
				server.Start();

				// Buffer for reading data
				Byte[] bytes = new Byte[256];
				String data = null;

				// Enter the listening loop.
				while (true)
				{
					Console.Write("Waiting for a connection... ");

					// Perform a blocking call to accept requests.
					// You could also user server.AcceptSocket() here.
					TcpClient client = server.AcceptTcpClient();
					Console.WriteLine("Connected!");

					data = null;

					// Get a stream object for reading and writing
					NetworkStream stream = client.GetStream();

					int i;
					string results = string.Empty;
					// Loop to receive all the data sent by the client.
					while ((i = stream.Read(bytes, 0, bytes.Length)) != 0 && (data == null || data.IndexOf("\0") < 1))
					{
						// Translate data bytes to a ASCII string.
						data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
						Console.WriteLine("\r\nReceived: {0}", data);

						// Process the data sent by the client.
						if (data.IndexOf("\0") < 1)
						{
							results += data;
						}
						else
						{
							// we actually don't send the data basck, but just drop it in a temp. file and return the file name.
							// this makes all the buffer handling in the extension much simpler.
							results += data.Substring(0, data.IndexOf("\0"));
							string content = ProcessRequest(results);

							// if we're sending more data then the extension much have done with the last
							// so tidy up if necessary.
							if (File.Exists(lastTmpFileName))
								File.Delete(lastTmpFileName);

							string response = Path.GetTempFileName();
							File.WriteAllText(response, content);
							lastTmpFileName = response;

							byte[] msg = System.Text.Encoding.ASCII.GetBytes(response + "\0");
							results = string.Empty;
							// Send back a response.
							stream.Write(msg, 0, msg.Length);


							Console.WriteLine("\r\nSent: {0}\r\n", Encoding.ASCII.GetString(msg));
						}
					}

					// Shutdown and end connection
					client.Close();
				}
			}
			catch (SocketException e)
			{
				Console.WriteLine("SocketException: {0}", e);
			}
			finally
			{
				// Stop listening for new clients.
				server.Stop();
			}
			StartListener();
		}

		private string ProcessRequest(string results)
		{
			if (File.Exists(results))
			{
				string fileName = results;
				results = File.ReadAllText(fileName);
				File.Delete(fileName);
			}
			Console.WriteLine("Processing request: {0}", results);
			string command = results.Substring(0, results.IndexOf('|'));
			string args = results.Substring(results.IndexOf('|') + 1);
			switch (command)
			{

				case "GETMENUS":
					{
						Dictionary<string, ContextMenuAttribute> menus = serverFunctions.GetMenus(args);
						List<string> menuList=new List<string>();
						foreach (KeyValuePair<string, ContextMenuAttribute> kvp in menus)
						{
							menuList.Add((kvp.Value.Disabled ? "_" : string.Empty) + kvp.Value.Text);
						}
						string data = string.Join("|", menuList.ToArray())+"\0";
						return data;
						break;
					}
				case "CALLMENU":
					{
						string sMenu = args.Substring(0, args.IndexOf('|'));
						string paths = args.Substring(args.IndexOf('|') + 1);
						int menu = 0;
						int.TryParse(sMenu, out menu);
						serverFunctions.RunMenuCommand(menu, paths, ContextMenuUsage.ExplorerOnly);
						break;
					}
				case "GETCOLDATA":
					{
						string sColData = args.Substring(0, args.IndexOf('|'));
						string path = args.Substring(args.IndexOf('|') + 1);
						int colData = 0;
						int.TryParse(sColData, out colData);
						string data = serverFunctions.GetColData(colData, path);
						return data;
						break;
					}
				case "GETFILEINFOS":
					{
						string path = args;
						string data = serverFunctions.GetFileInfos(path);
						return data;
						break;
					}
				case "GETICONSTATUS":
					{
						string path = args.Substring(0, args.IndexOf('|'));
						string overlayType = args.Substring(args.IndexOf('|') + 1);
						string data = serverFunctions.GetFilesForOverlayType(path, overlayType);
						return data;
						break;
					}
				case "GETLIZARDSTATUS":
					{
						string path = args;
						if (path.EndsWith("\\"))
							path = path.Substring(0, path.Length - 1);
						if (File.Exists(path))
							path = Path.GetDirectoryName(path);
						string data = "FALSE";
						if (Directory.Exists( ServerConnections.GetConnectionForPath(path).GetMetaFolder(path)))
							data="TRUE";

						return data;
						break;
					}
			}
			return string.Empty;
		}
	}
}
